package com.qire.manhua.model.viewModel.impl;

import android.app.Activity;
import android.os.CountDownTimer;
import android.view.View;
import android.widget.EditText;

import com.qire.antscore.annotation.PropertyObserve;
import com.qire.antsrouter.AntsRouter;
import com.qire.antsrouter.card.FloorCard;
import com.qire.common.basic.ObjectUtil;
import com.qire.common.basic.StringUtil;
import com.qire.common.collect.ListUtil;
import com.qire.common.constant.Navigation;
import com.qire.common.model.entity.UserEntity;
import com.qire.common.support.DialogFastBuildUtil;
import com.qire.common.support.base.BaseViewModel;
import com.qire.common.utils.CountDownTimerBuilder;
import com.qire.common.utils.ToastHelper;
import com.qire.manhua.R;
import com.qire.manhua.dal.service.AccountCancellationGuideService;
import com.qire.manhua.databinding.ActivityAccountCancellationGuideBinding;
import com.qire.manhua.model.enumeration.AccountBusinessPanelLayout;
import com.qire.manhua.model.viewModel.IAccountCancellationGuideViewModel;

import net.yslibrary.android.keyboardvisibilityevent.util.UIUtil;

import java.util.Arrays;
import java.util.Stack;
import java.util.concurrent.TimeUnit;

public class AccountCancellationGuideViewModel extends BaseViewModel<IAccountCancellationGuideViewModel> {

    private AccountCancellationGuideService cancellationGuideService = new AccountCancellationGuideService(this);

    private ActivityAccountCancellationGuideBinding viewDataBinder;

    //region    #附加管理 begin
    public void onAddition(ActivityAccountCancellationGuideBinding viewDataBinder) {
        this.viewDataBinder = viewDataBinder;
        cancellationGuideService.accountCancellationQuery();
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        this.viewDataBinder = null;
    }
    //endregion #附加管理 end

    //region    #业务与数据 begin
    /** 手机号码有效验证 */
    public boolean phoneIsValid(String phone) {
        return StringUtil.notEmpty(phone) && StringUtil.isMobile(phone);
    }

    /** 申诉信息有效验证 */
    public boolean appealInfoIsValid(String contactPhone, String contactTime, String note) {
        if(StringUtil.isEmpty(contactPhone)/* || !StringUtil.isMobile(contactPhone)*/)
            return false;
        if(StringUtil.isEmpty(contactTime))
            return false;
        if(StringUtil.isEmpty(note))
            return false;
        return true;
    }

    public String phoneNumber() {
        return StringUtil.defValue(UserEntity.self.getMobile(), "");
    }

    /** 原手机号码验证 */
    public void authOldPhoneNumber() {
        String oldPhone = getToValue("oldPhone", "");
        if(phoneIsValid(oldPhone)) {
            cancellationGuideService.authPhoneNumberBy(oldPhone);
        } else {
            ToastHelper.showToast("无效的手机号码");
        }
    }

    /** 获取验证码 */
    public void fetchVerificationCode() {
        startCountDown();
        requestVerifyCode1Focus();
        cancellationGuideService.fetchVerificationCode(phoneNumber());
    }

    /** 校验验证码 */
    public void checkVerificationCode() {
        if(verifyCodeIsValid()) {
            cancellationGuideService.checkVerificationCode(phoneNumber(), verifyCode());
        } else {
            ToastHelper.showToast("无效的验证码");
        }
    }

    /** 注销前核查账户消费订单数据 */
    public void checkBeforeCancellationAccount() {
        cancellationGuideService.checkBeforeCancellationAccount();
    }

    /** 注销当前账户 */
    private void accountCancellation() {
        cancellationGuideService.accountCancellation();
    }

    /** 注销当前账户通过人工 */
    public void accountCancellationByArtificial() {
        String phoneNumber = UserEntity.self.getMobile();
        String contactPhone = getToValue("contactPhone", "");
        String appointmentTime = getToValue("contactTime", "");
        String reason = getToValue("note", "");
        cancellationGuideService.accountCancellationByArtificial(phoneNumber, contactPhone, appointmentTime, reason);
    }
    //endregion #业务与数据 end

    //region    #dialog管理 begin
    public void showAccountCheckSuccessInfoDialog(String checkInfo) {
        DialogFastBuildUtil.builder(R.layout.dialog_common_prompt_light_l)
                .setTextView(R.id.dialog_title, "销户提示")
                .setTextView(R.id.dialog_content, checkInfo)
                .setTextView(R.id.dialog_button_light, "确认", view -> {
                    accountCancellation();
                    DialogFastBuildUtil.dismissDialogBy(view);
                })
                .setTextView(R.id.dialog_button_dark, "取消", DialogFastBuildUtil::dismissDialogBy)
                .show();
    }

    public void showAccountCheckFailedInfoDialog(final String tipsText, final String tipsBtnText, final String actTitle, final String actUrl) {
        DialogFastBuildUtil.builder(R.layout.dialog_common_prompt_light_l)
                .setTextView(R.id.dialog_title, "销户提示")
                .setTextView(R.id.dialog_content, tipsText)
                .setTextView(R.id.dialog_button_light, tipsBtnText, view -> {
                    AntsRouter.ROUTER.<FloorCard>buildCard(Navigation.Page.WebPage)
                            .withData("title", actTitle)
                            .withData("url", actUrl)
                            .navigation();
                    DialogFastBuildUtil.dismissDialogBy(view);
                })
                .setTextView(R.id.dialog_button_dark, "关闭", DialogFastBuildUtil::dismissDialogBy)
                .show();
    }
    //endregion #dialog管理 end

    //region    #面板控制 begin
    private final Stack<AccountBusinessPanelLayout> pageStack = new Stack<>();
    private AccountBusinessPanelLayout currentPanelLayout = null;

    public void initPanelLayout() {
        pageStack.clear();
        set("oldPhone", "");
        set("agreeToDeal", agreeToDeal());
        set("verifyPhoneNumberHint", String.format("请先验证手机号:%s", StringUtil.replace("****", UserEntity.self.getMobile(), 3)));
        refreshSubmitBtnUI("", "", "");
        if(UserEntity.self.haveBindMobile()) {
            AccountBusinessPanelLayout.AccountCancellationPhoneVerifyWay.addNext(AccountBusinessPanelLayout.CodeVerify);
            gotoPage(AccountBusinessPanelLayout.AccountCancellationPhoneVerifyWay);
        } else {
            AccountBusinessPanelLayout.AccountCancellationNotice.addNext(AccountBusinessPanelLayout.AccountCancellationGuideFinishHint);
            gotoPage(AccountBusinessPanelLayout.AccountCancellationNotice);
        }
    }

    /**
     * 返回上一个面板，如果是顶层结束面板则直接返回 true；
     * @return 如果当前面板不是顶层结束面板则返回false，否则返回true。
     */
    public boolean backPanel() {
        if(ListUtil.isEmpty(pageStack) || currentPanelLayout.isFinish) {
            return true;
        }
        refreshPage(pageStack.pop());
        return false;
    }

    public void nextPage() {
        if(currentPanelLayout == null) {
            return;
        }
        if(currentPanelLayout.next() == null) {
            return;
        }
        if(currentPanelLayout.needRecycle()) {
            pageStack.push(currentPanelLayout);
        }
        refreshPage(currentPanelLayout.next());
    }

    public void gotoPage(AccountBusinessPanelLayout page) {
        if(currentPanelLayout != null) {
            pageStack.push(currentPanelLayout);
        }
        refreshPage(page);
    }

    private void refreshPage(AccountBusinessPanelLayout page) {
        this.currentPanelLayout = page;

        hideKeyBoard();
        resetVerifyCode();
        resetGetCodeButton();

        int[] layoutVisible = new int[8];
        Arrays.fill(layoutVisible, View.GONE);
        switch (currentPanelLayout) {
            case AccountCancellationPhoneVerifyWay:
                layoutVisible[0] = View.VISIBLE; break;
            case CodeVerify:
                layoutVisible[1] = View.VISIBLE; break;
            case OldPhoneVerify:
                layoutVisible[2] = View.VISIBLE; break;
            case AccountCancellationByAppeal:
                layoutVisible[3] = View.VISIBLE; break;
            case AccountCancellationWaiting:
                layoutVisible[4] = View.VISIBLE; break;
            case AccountCancellationArtificialAppealsPass:
                layoutVisible[5] = View.VISIBLE; break;
            case AccountCancellationNotice:
                layoutVisible[6] = View.VISIBLE; break;
            case AccountCancellationGuideFinishHint:
                layoutVisible[7] = View.VISIBLE; break;
        }
        set("layoutVisible", layoutVisible);
        set("title", currentPanelLayout != null ? currentPanelLayout.pageTitle : "手机号绑定");
    }

    private void hideKeyBoard() {
        UIUtil.hideKeyboard((Activity) viewDataBinder.getRoot().getContext());
    }

    public void showArtificialResults(String applyDateInfo, String contactInfo, String makeAppointmentTime, String applyReason) {
        set("applyDateInfo", String.format("申请时间：%s", applyDateInfo));
        set("contactInfo", String.format("联系方式：%s", contactInfo));
        set("makeAppointmentTime", String.format("预约时间：%s", makeAppointmentTime));
        set("applyReason", String.format("申请原因：%s", applyReason));
    }
    //endregion #面板控制 end

    //region    #验证码 begin
    private int verifyCode1 = -1;
    private int verifyCode2 = -1;
    private int verifyCode3 = -1;
    private int verifyCode4 = -1;

    /** 验证码计时器*/
    private CountDownTimer timer;

    public void requestVerifyCode1Focus() {
        final EditText focusView = viewDataBinder.verifyCode1;
        focusView.requestFocus();
        focusView.postDelayed(()-> UIUtil.showKeyboard(focusView.getContext(), focusView), 300);
    }

    /** 获取验证码倒计时*/
    private void startCountDown() {
        if(ObjectUtil.nonNull(timer)) {
            timer.cancel();
            timer.onFinish();
        }

        setFetchVerifyCodeTextEnabled(false);
        timer = CountDownTimerBuilder.build(60, 1, TimeUnit.SECONDS)
                .addTickCallBack((countDownTime, timeUnit) -> {
                    setFetchVerifyCodeText(String.format("重新获取(%ss)", countDownTime--));
                    return countDownTime;
                })
                .addFinishCallBack((countDownTime, timeUnit) -> {
                    resetGetCodeButton();
                    return countDownTime;
                }).start();
    }
    /** 恢复获取验证码按钮*/
    public void resetGetCodeButton() {
        if(ObjectUtil.nonNull(timer)) {
            timer.cancel();
        }
        setFetchVerifyCodeText("重新获取");
        setFetchVerifyCodeTextEnabled(true);
    }

    private void setFetchVerifyCodeText(CharSequence fetchVerifyCodeText) {
        set("fetchVerifyCodeText", fetchVerifyCodeText);
    }

    private void setFetchVerifyCodeTextEnabled(boolean fetchVerifyCodeTextEnabled) {
        set("fetchVerifyCodeTextColor", fetchVerifyCodeTextEnabled ? "#ff9204" : "#aeaeae");
        set("fetchVerifyCodeTextEnabled", fetchVerifyCodeTextEnabled);
    }

    private void resetVerifyCode() {
        set("verifyCode1", "");
        set("verifyCode2", "");
        set("verifyCode3", "");
        set("verifyCode4", "");
        resetGetCodeButton();

        String coverNumber = StringUtil.replace("****", phoneNumber(), 3);
        set("phoneNumberHint", coverNumber);
    }

    private String verifyCode() {
        return String.format("%s%s%s%s", verifyCode1, verifyCode2, verifyCode3, verifyCode4);
    }

    private boolean verifyCodeIsValid() {
        return verifyCode1 >= 0 && verifyCode2 >= 0 && verifyCode3 >= 0 && verifyCode4 >= 0;
    }

    /**
     * 刷新验证码确认按钮状态
     */
    private void refreshVerifyBtn() {
        put("verifyBtnEnabled", verifyCodeIsValid());
        put("verifyBtnTextColor", verifyCodeIsValid() ? "#423300" : "#aeaeae");
        put("verifyBtnBackground", verifyCodeIsValid() ? R.drawable.app_accounts_associated_bg_yellow : R.drawable.app_accounts_associated_bg_gray);
    }

    /**
     * 以下是4个验证码输入框的状态监听，如果输入框内容发生改变则会触发观察者消息
     */
    @PropertyObserve(name = "verifyCode1")
    public void setVerifyCode1(String verifyCode1) {
        try {
            int codeValue = Integer.valueOf(verifyCode1);
            // 解决光标位置问题导致可能最新输入的字符在旧字符前需要判断故做一下数值运算处理，始终使用最新值替换旧值；
            if(codeValue != this.verifyCode1 || verifyCode1.length() > 1) {
                this.verifyCode1 = codeValue % 10 == this.verifyCode1 ? codeValue / 10 : codeValue % 10;
                set("verifyCode1", String.valueOf(this.verifyCode1));
            }
            viewDataBinder.verifyCode2.requestFocus();
        } catch(Exception e) {
            this.verifyCode1 = -1;
        }
        refreshVerifyBtn();
    }
    @PropertyObserve(name = "verifyCode2")
    public void setVerifyCode2(String verifyCode2) {
        try {
            int codeValue = Integer.valueOf(verifyCode2);
            if(codeValue != this.verifyCode2 || verifyCode2.length() > 1) {
                this.verifyCode2 = codeValue % 10 == this.verifyCode2 ? codeValue / 10 : codeValue % 10;
                set("verifyCode2", String.valueOf(this.verifyCode2));
            }
            viewDataBinder.verifyCode3.requestFocus();
        } catch(Exception e) {
            this.verifyCode2 = -1;
            viewDataBinder.verifyCode1.requestFocus();
        }
        refreshVerifyBtn();
    }
    @PropertyObserve(name = "verifyCode3")
    public void setVerifyCode3(String verifyCode3) {
        try {
            int codeValue = Integer.valueOf(verifyCode3);
            if(codeValue != this.verifyCode3 || verifyCode3.length() > 1) {
                this.verifyCode3 = codeValue % 10 == this.verifyCode3 ? codeValue / 10 : codeValue % 10;
                set("verifyCode3", String.valueOf(this.verifyCode3));
            }
            viewDataBinder.verifyCode4.requestFocus();
        } catch(Exception e) {
            this.verifyCode3 = -1;
            viewDataBinder.verifyCode2.requestFocus();
        }
        refreshVerifyBtn();
    }
    @PropertyObserve(name = "verifyCode4")
    public void setVerifyCode4(String verifyCode4) {
        try {
            int codeValue = Integer.valueOf(verifyCode4);
            if(codeValue != this.verifyCode4 || verifyCode4.length() > 1) {
                this.verifyCode4 = codeValue % 10 == this.verifyCode4 ? codeValue / 10 : codeValue % 10;
                set("verifyCode4", String.valueOf(this.verifyCode4));
            }
        } catch(Exception e) {
            this.verifyCode4 = -1;
            viewDataBinder.verifyCode3.requestFocus();
        }
        refreshVerifyBtn();
    }
    //endregion #验证码 end

    //region    #关联更新 begin
    public boolean agreeToDeal() {
        return getToValue("agreeToDeal", false);
    }
    public void toggleAgreeToDeal() {
        set("agreeToDeal", !agreeToDeal());
    }
    @PropertyObserve(name = "agreeToDeal")
    public void onAgreeToDealChange(boolean agreeToDeal) {
        set("appliesForCancellationBtnEnabled", agreeToDeal);
        set("appliesForCancellationBtnTextColor", agreeToDeal ? "#423300" : "#aeaeae");
        set("appliesForCancellationBtnBackground", agreeToDeal ? R.drawable.app_common_button_yellow : R.drawable.app_account_bg_grey_round);
    }

    @PropertyObserve(name = "oldPhone")
    public void onOldPhoneChange(String oldPhone) {
        boolean oldPhoneIsValid = phoneIsValid(oldPhone);
        set("oldPhoneVerifyButtonEnabled", oldPhoneIsValid);
        set("oldPhoneVerifyButtonTextColor", oldPhoneIsValid ? "#423300" : "#aeaeae");
        set("oldPhoneVerifyButtonBackground", oldPhoneIsValid ?  R.drawable.app_common_button_yellow : R.drawable.app_account_bg_grey_round);
    }

    @PropertyObserve(name = "contactPhone")
    public void onContactPhoneChange(String contactPhone) {
        String contactTime = getToValue("contactTime", "");
        String note = getToValue("note", "");
        refreshSubmitBtnUI(contactPhone, contactTime, note);
    }
    @PropertyObserve(name = "contactTime")
    public void onContactTimeChange(String contactTime) {
        String contactPhone = getToValue("contactPhone", "");
        String note = getToValue("note", "");
        refreshSubmitBtnUI(contactPhone, contactTime, note);
    }
    @PropertyObserve(name = "note")
    public void onNoteChange(String note) {
        String contactPhone = getToValue("contactPhone", "");
        String contactTime = getToValue("contactTime", "");
        refreshSubmitBtnUI(contactPhone, contactTime, note);
    }
    private void refreshSubmitBtnUI(String contactPhone, String contactTime, String note) {
        boolean appealInfoIsValid = appealInfoIsValid(contactPhone, contactTime, note);
        set("submitBtnEnabled", appealInfoIsValid);
        set("submitBtnTextColor", appealInfoIsValid ? "#423300" : "#aeaeae");
        set("submitBtnBackground", appealInfoIsValid ?  R.drawable.app_common_button_yellow : R.drawable.app_account_bind_bg_gray);
    }
    //endregion #关联更新 end

}
